package cn.agiledata.bank.common.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * The list whose size is long type, and max size is Long.MAX_VALUE
 * 
 * @author 马贤波
 * 
 */
public class LongList {
    /**
     * 每个list的最大大小
     */
    private static final int PER_LIST_MAX_SIZE = Integer.MAX_VALUE;

    private List lists;

    public LongList() {
        this.lists = new ArrayList();
    }

    /**
     * 
     * @return 最后一个非空的list
     */
    private List getLastList() {
        List lastList = this.lists.size() == 0 ? null : (List) this.lists
                .get(this.lists.size() - 1);
        if (lastList == null || lastList.size() == PER_LIST_MAX_SIZE) {
            lastList = new ArrayList();
            this.lists.add(lastList);
        } else {
            // 删除多余的空list
            while (lastList.size() == 0 && this.lists.size() > 1) {
                List last2List = (List) this.lists.get(this.lists.size() - 2);
                if (last2List.size() == PER_LIST_MAX_SIZE) {
                    break;
                }
                this.lists.remove(this.lists.size() - 1);
                lastList = (List) this.lists.get(this.lists.size() - 1);
            }
        }
        return lastList;
    }

    /**
     * 根据指定索引值获取索引位置处于第几个list中
     */
    private int getListIndex(long index) {
        return (int) index / PER_LIST_MAX_SIZE;
    }

    /**
     * 根据指定索引值获取索引位置处于所属list中的索引值
     */
    private int getElementIndex(long index) {
        return (int) index % PER_LIST_MAX_SIZE;
    }

    public boolean add(Object o) {
        return getLastList().add(o);
    }

    public boolean addAll(Collection c) {
        int addSize = c.size();
        List lastList = getLastList();
        int lastSize = lastList.size();
        int length = addSize <= (PER_LIST_MAX_SIZE - lastSize) ? addSize
                : (PER_LIST_MAX_SIZE - lastSize);
        Iterator it = c.iterator();
        for (int i = 0; i < length; i++) {
            lastList.add(it.next());
        }
        if (addSize > length) {
            lastList = getLastList();
            while (it.hasNext()) {
                lastList.add(it.next());
            }
        }
        return true;
    }

    public Object get(long index) {
        if (index < 0 || index >= size()) {
            throw new IndexOutOfBoundsException("The index is out of bounds : "
                    + index);
        }
        List list = (List) this.lists.get(getListIndex(index));
        return list.get(getElementIndex(index));
    }

    public Object remove(long index) {
        long size = size();
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("The index is out of bounds : "
                    + index);
        }
        List list = (List) this.lists.get(getListIndex(index));
        Object o = list.get(getElementIndex(index));
        for (long i = index; i < size - 1; i++) {
            set(i, get(i + 1));
        }
        List lastList = getLastList();
        // 删除多余的空list
        while (lastList.size() == 0 && this.lists.size() > 1) {
            this.lists.remove(this.lists.size() - 1);
            lastList = (List) this.lists.get(this.lists.size() - 1);
        }
        lastList.remove(lastList.size() - 1);
        return o;
    }

    public Object set(long index, Object o) {
        if (index < 0 || index >= size()) {
            throw new IndexOutOfBoundsException("The index is out of bounds : "
                    + index);
        }
        List list = (List) this.lists.get(getListIndex(index));
        return list.set(getElementIndex(index), o);
    }

    public void clear() {
        this.lists.clear();
    }

    public long indexOf(Object o) {
        int listCount = this.lists.size();
        if (listCount == 0)
            return -1;
        long index = 0;
        for (int i = 0; i < listCount; i++) {
            List list = (List) this.lists.get(i);
            int elementIndex = list.indexOf(o);
            if (elementIndex < 0) {
                index += list.size();
            } else {
                index += elementIndex;
                return index;
            }
        }
        return -1;
    }

    public long lastIndexOf(Object o) {
        int listCount = this.lists.size();
        if (listCount == 0)
            return -1;
        long index = size();
        for (int i = listCount - 1; i >= 0; i--) {
            List list = (List) this.lists.get(i);
            index -= list.size();
            int elementIndex = list.lastIndexOf(o);
            if (elementIndex >= 0) {
                index += elementIndex;
                return index;
            }
        }
        return -1;
    }

    public long size() {
        long size = 0;
        for (Iterator it = this.lists.iterator(); it.hasNext();) {
            List list = (List) it.next();
            size += list.size();
        }
        return size;
    }

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof LongList)) {
            return false;
        }
        LongList ll = (LongList) o;
        return this.lists.equals(ll.lists);
    }

    public String toString() {
        String s = "";
        long size = size();
        for (long i = 0; i < size; i++) {
            s += "," + get(i);
        }
        if (s.length() > 0) {
            s = s.substring(1);
        }
        s = "[" + s + "]";
        return s;
    }

}
